import java.awt.Color;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Vector;

import javax.imageio.ImageIO;

public class Principal {

	/**
	 * @param args
	 */
	  private static RenderingHints opciones = new RenderingHints(null);

	static BufferedImage originalImage = null;
	static BufferedImage TransformedImage = null;
	static int alto;
	static int ancho;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// AQUI PON EN NOMBRE DEL ARCHIVO QUE QUIERES LEER
		File imageFile = new File("imagen.jpg");

		try {
			originalImage = ImageIO.read(imageFile);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		alto = originalImage.getHeight();
		ancho = originalImage.getWidth();
		TransformedImage = gris(originalImage);
		// saveFile(new File("imagen2.jpg"));
		TransformedImage = umbral(TransformedImage);
		// AQUI PON EL NOMBRE O LA RUTA DONDE QUIERES GUARDAR EL ARCHIVO
		saveFile(new File("imagen3.jpg"), TransformedImage);
		Matricula m = buscarMatricula(TransformedImage);
		System.out.println(ocr(m));

	}

	public static void saveFile(File imageFile, BufferedImage image) {
		try {
			ImageIO.write(image, "jpg", imageFile);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static BufferedImage gris(BufferedImage imagen) {
		BufferedImage aux = null;
		aux = new BufferedImage(imagen.getWidth(), imagen.getHeight(),
				BufferedImage.TYPE_BYTE_GRAY);
		for (int i = 0; i < imagen.getWidth(); i++) {
			for (int j = 0; j < imagen.getHeight(); j++) {
				aux.setRGB(i, j, imagen.getRGB(i, j));
			}

		}
		return aux;

	}

	public static BufferedImage filtroBajo(BufferedImage imagen) {
		BufferedImage aux = null;
		aux = new BufferedImage(imagen.getWidth(), imagen.getHeight(),
				BufferedImage.TYPE_BYTE_GRAY);
		for (int i = 0; i < imagen.getWidth(); i++) {
			for (int j = 0; j < imagen.getHeight(); j++) {
				int valor = 0;
				int contador = 0;

				if ((i > 0) && (j > 0)) {
					Color c = new Color(imagen.getRGB(i - 1, j - 1));
					int color = (c.getRed() + c.getBlue() + c.getGreen()) / 3;
					valor += color;
					contador++;
				}
				if (i > 0) {
					Color c = new Color(imagen.getRGB(i - 1, j));
					int color = (c.getRed() + c.getBlue() + c.getGreen()) / 3;
					valor += color;
					contador++;
				}
				if ((i > 0) && (j < imagen.getHeight() - 1)) {
					Color c = new Color(imagen.getRGB(i - 1, j + 1));
					int color = (c.getRed() + c.getBlue() + c.getGreen()) / 3;
					valor += color;
					contador++;
				}
				if (j > 0) {
					Color c = new Color(imagen.getRGB(i, j - 1));
					int color = (c.getRed() + c.getBlue() + c.getGreen()) / 3;
					valor += color;
					contador++;
				}
				Color c1 = new Color(imagen.getRGB(i, j));
				int color1 = (c1.getRed() + c1.getBlue() + c1.getGreen()) / 3;
				valor += color1;
				contador++;
				if (j < imagen.getHeight() - 1) {
					Color c = new Color(imagen.getRGB(i, j + 1));
					int color = (c.getRed() + c.getBlue() + c.getGreen()) / 3;
					valor += color;
					contador++;
				}
				if ((i < imagen.getWidth() - 1) && (j > 0)) {
					Color c = new Color(imagen.getRGB(i + 1, j - 1));
					int color = (c.getRed() + c.getBlue() + c.getGreen()) / 3;
					valor += color;
					contador++;
				}
				if (i < imagen.getWidth() - 1) {
					Color c = new Color(imagen.getRGB(i + 1, j));
					int color = (c.getRed() + c.getBlue() + c.getGreen()) / 3;
					valor += color;
					contador++;
				}
				if ((i < imagen.getWidth() - 1) && (j < imagen.getHeight() - 1)) {
					Color c = new Color(imagen.getRGB(i + 1, j + 1));
					int color = (c.getRed() + c.getBlue() + c.getGreen()) / 3;
					valor += color;
					contador++;
				}
				Color c = new Color(valor / contador);
				// System.out.println("guardo el pixel "+i+" "+j+"con valor"+
				// c.getRGB());

				aux.setRGB(i, j, c.getRGB());
			}
		}
		return aux;

	}

	public static BufferedImage umbral(BufferedImage imagen) {

		BufferedImage aux = null;
		aux = new BufferedImage(imagen.getWidth(), imagen.getHeight(),
				BufferedImage.TYPE_BYTE_GRAY);
		for (int i = 0; i < imagen.getWidth(); i++) {
			for (int j = 0; j < imagen.getHeight(); j++) {
				Color c = new Color(imagen.getRGB(i, j));
				int color = (c.getRed() + c.getBlue() + c.getGreen()) / 3;
				if (color < 127) {
					Color c1 = new Color(000000);
					aux.setRGB(i, j, c1.getRGB());
				} else {
					Color c1 = new Color((255 << 16) | (255 << 8) | 255);
					aux.setRGB(i, j, c1.getRGB());
				}
			}
		}
		return aux;
	}

	public static Matricula buscarMatricula(BufferedImage imagen) {
		Matricula mimatricula = null;
		Vector<Punto> puntos = new Vector<Punto>();
		Vector<Punto> puntosComprobados = new Vector<Punto>();
		BufferedImage aux = null;
		for (int i = 0; i < imagen.getWidth(); i++) {
			for (int j = 0; j < imagen.getHeight(); j++) {
				Color c = new Color(imagen.getRGB(i, j));
				int color = (c.getRed() + c.getBlue() + c.getGreen()) / 3;
				if (color == 255) {
					boolean seguir = true;
					int blancos = 0;
					int negros = 0;
					while (seguir) {
						if (j + blancos < imagen.getHeight()) {
							Color c2 = new Color(imagen.getRGB(i, j + blancos));
							int color2 = (c2.getRed() + c2.getBlue() + c2
									.getGreen()) / 3;
							if (color2 == 255) {
								blancos += negros;
								blancos++;
								negros = 0;
							} else {
								negros++;
							}
						} else {
							seguir = false;
						}
						if (negros > 50) {// Negros permitidos

							seguir = false;
						}
					}
					if (blancos > 120) {
						puntos.add(new Punto(i, j, blancos));
						j += blancos;
					} else {
						j += blancos;
					}
				}
			}
		}
		// ----------------------------------------------------
		Vector<Integer> lista = new Vector<Integer>();
		for (int i = 0; i < puntos.size(); i++) {
			int k = puntos.elementAt(i).getY();

			if (lista.indexOf(k) == -1) {
				lista.add(k);
				for (int j = 0; j < imagen.getWidth(); j++) {
					Color c = new Color(imagen.getRGB(j, k));
					int color = (c.getRed() + c.getBlue() + c.getGreen()) / 3;
					if (color == 255) {
						boolean seguir = true;
						int blancos = 0;
						int negros = 0;
						while (seguir) {
							if (j + blancos < imagen.getWidth()) {
								Color c2 = new Color(imagen.getRGB(j + blancos,
										k));
								int color2 = (c2.getRed() + c2.getBlue() + c2
										.getGreen()) / 3;
								if (color2 == 255) {
									blancos += negros;
									blancos++;
									negros = 0;
								} else {
									negros++;
								}
							} else {
								seguir = false;
							}
							if (negros > 50) {// Negros permitidos
								seguir = false;
							}
						}
						if (blancos > 650) {
							puntosComprobados.add(new Punto(j, k, blancos));
							j += blancos;
						} else {
							j += blancos;
						}
					}
				}
			}
		}

		Vector<PuntosConfirmados> confirmados = new Vector<PuntosConfirmados>();
		for (int i = 0; i < puntos.size(); i++) {
			for (int j = 0; j < puntosComprobados.size(); j++) {
				if (puntos.elementAt(i).getY() == puntosComprobados
						.elementAt(j).getY()) {
					if ((puntosComprobados.elementAt(j).getSeguidos() / puntos
							.elementAt(i).getSeguidos()) < 5.1
							&& (puntosComprobados.elementAt(j).getSeguidos() / puntos
									.elementAt(i).getSeguidos()) > 4.9) {
						confirmados.add(new PuntosConfirmados(puntos
								.elementAt(i), puntosComprobados.elementAt(j)));
						System.out.println(puntos.elementAt(i).toString() + "|"
								+ puntosComprobados.elementAt(j).toString());
						// VER LA MATRICULA

						aux = new BufferedImage(puntosComprobados.elementAt(j)
								.getSeguidos()/* +20 */, puntos.elementAt(i)
								.getSeguidos()/* +20 */,
								BufferedImage.TYPE_BYTE_GRAY);
						int vertical = 0, horizontal = 0;
						vertical = puntos.elementAt(i).getY()/*-10*/;
						if (puntosComprobados.elementAt(j).getX() > puntos
								.elementAt(i).getX()) {
							horizontal = puntos.elementAt(j).getX()/*-10*/;
							for (int x = 0; x < puntosComprobados.elementAt(j)
									.getSeguidos()/* +20 */; x++) {
								for (int y = 0; y < puntos.elementAt(i)
										.getSeguidos()/* +20 */; y++) {
									aux.setRGB(x, y, imagen.getRGB(x
											+ horizontal, y + vertical));

								}
							}
						} else {

							horizontal = puntosComprobados.elementAt(j).getX()/*-5*/;
							for (int x = 0; x < puntosComprobados.elementAt(j)
									.getSeguidos()/* +20 */; x++) {
								for (int y = 0; y < puntos.elementAt(i)
										.getSeguidos()/* +20 */; y++) {
									aux.setRGB(x, y, imagen.getRGB(x
											+ horizontal, y + vertical));

								}
							}
						}
						saveFile(new File(i + ".jpg"), aux);
						mimatricula = new Matricula(aux, 1, puntosComprobados
								.elementAt(j).getSeguidos() + 20, puntos
								.elementAt(i).getSeguidos() + 20);
						// break;

					}
				}
			}

		}

		return mimatricula;
	}

	@SuppressWarnings("unchecked")
	public static String ocr(Matricula mat) {
		int veces=0;
		String matricula="";
		int anchoNumero = (45 * mat.horizontal) / 510;
		int altoNumero = (77 * mat.horizontal) / 510;
		int grosorNumero = (10 * mat.horizontal) / 510;
		int separacion= (14 * mat.horizontal) / 510;
		System.out.println(anchoNumero + "|" + altoNumero + "|" + grosorNumero);
		Vector<Integer> posiciones = new Vector();
		for (int i = 0; i < mat.getMatricula().getWidth(); i++) {
			int j = 0;
			boolean seguir = true;
			int negros = 0;
			while (seguir) {
				if (j < mat.getMatricula().getHeight()) {
					Color c2 = new Color(mat.getMatricula().getRGB(i, j));
					int color2 = (c2.getRed() + c2.getBlue() + c2.getGreen()) / 3;
					if (color2 == 255) {
						negros = 0;
					} else {
						negros++;
					}
				} else {
					break;
				}
				if (negros > 10) {// Negros permitidos

					seguir = false;
					
				}
				j++;
			}
			if (!seguir) {
				posiciones.add(i);
			}

			if ((!seguir)&&(posiciones.size()>5)) {
				BufferedImage aux = new BufferedImage(anchoNumero + 5,
						altoNumero + 5, BufferedImage.TYPE_BYTE_GRAY);
				int sobrante = (mat.getMatricula().getHeight() - altoNumero) / 2;

				if (i + anchoNumero  < mat.getMatricula().getWidth()) {
					for (int n = 0; n < anchoNumero + 5; n++) {
						for (int t = 0; t < altoNumero + 5; t++) {
							aux.setRGB(n, t, mat.getMatricula().getRGB(n + i-5,
									t + sobrante));
						}
					}
					//*************************************/
					/*System.out.println("entro" + i);
					
					File imageF = new File("D:\\vision\\Practica\\numeros\\2.jpg");
					BufferedImage dos = null;
					try {
						dos=ImageIO.read(imageF);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(compararImagen(dos,aux));
					//saveFile(new File("caracter" + j + ".jpg"), aux);
					i += anchoNumero +separacion;*/
					String dir="";
					if(veces<4){
					    dir ="F:\\practicas\\vision\\Practica\\numeros\\";
					}else{
						dir ="F:\\practicas\\vision\\Practica\\letras\\";
					}
					veces++;
					File carpeta = new File(dir);
					String[] archi=carpeta.list();
					int porcentaje=0;
					String caracter=null;
					//System.out.println(archi.length);
					for(int t=1; t<archi.length; t++) {
						String miarchivo=dir+"\\" + archi[t];
						// AQUI PON EN NOMBRE DEL ARCHIVO QUE QUIERES LEER
						File imageFile = new File(miarchivo);
						BufferedImage archivoImagen=null; 
						try {
							archivoImagen = ImageIO.read(imageFile);
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						int numero=compararImagen(aux,archivoImagen);
						if(numero>porcentaje){
							porcentaje=numero;
							caracter=miarchivo.substring(miarchivo.lastIndexOf("\\")+1, miarchivo.lastIndexOf("."));
							
						}
					}	
					
					matricula+=caracter;
					i += anchoNumero +separacion;
					}
				posiciones.clear();
			}
			

		}

		return matricula;
	}
	public static int compararImagen(BufferedImage imagen1,BufferedImage imagen2){
		BufferedImage i1=imagen1;
		BufferedImage i2=imagen2;
		int ancho=0;
		int alto=0;
		float factorAncho=(float)imagen2.getWidth()/imagen1.getWidth();
		float factorAlto=(float)imagen2.getHeight()/imagen1.getHeight();
		
		BufferedImage aux;
		AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(factorAncho,factorAlto), opciones);
		aux=op.filter(imagen1, null);
		i1=umbral(aux);
		i2=umbral(imagen2);
		ancho=i1.getWidth();
		alto=i1.getHeight();
		
		saveFile(new File("i1.jpg"),i1);
		saveFile(new File("i2.jpg"),i2);
		int iguales=0;
		for(int i =0; i<ancho;i++){
			for(int j=0; j<alto;j++){
				if(i1.getRGB(i, j)==i2.getRGB(i, j)){
					iguales++;
				}
			}
		}
		
		int porcentaje=((iguales*100/(alto*ancho)));
		
		return porcentaje;
	}

}
